Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ica submission strategy support in the cli #4980

Open
wants to merge 33 commits into
base: main
Choose a base branch
from

Conversation

xeno097
Copy link
Contributor

@xeno097 xeno097 commented Dec 10, 2024

Description

This PR updates the implementation for sending ICA transactions using the CLI when running warp apply and adds a relay flag so that ICA transactions can be self-relayed when using the JSON RPC strategy as the internal submission strategy.

Drive-by changes

  • Removes the transformer logic from the submitter getter

Related issues

Backward compatibility

  • No, the way to define how to send ICA transactions has changed compared to previous CLI versions

Testing

  • Manual
  • E2E

…to xeno/update-ism-derivation-for-ica-support
…ta building from on chain data to enable self relaying of ICA messages
…to xeno/update-ism-derivation-for-ica-support
…to xeno/ica-submission-strategy-support-in-the-cli
…one is supplied in the strategy file when using ICAs
…to xeno/ica-submission-strategy-support-in-the-cli
…to xeno/ica-submission-strategy-support-in-the-cli
…to xeno/ica-submission-strategy-support-in-the-cli
@xeno097 xeno097 requested a review from paulbalaji as a code owner December 10, 2024 14:42
Copy link

changeset-bot bot commented Dec 10, 2024

🦋 Changeset detected

Latest commit: 6b6357c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
@hyperlane-xyz/cli Major
@hyperlane-xyz/sdk Major
@hyperlane-xyz/helloworld Major
@hyperlane-xyz/infra Major
@hyperlane-xyz/widgets Major
@hyperlane-xyz/ccip-server Major
@hyperlane-xyz/github-proxy Major
@hyperlane-xyz/utils Major
@hyperlane-xyz/core Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@xeno097 xeno097 marked this pull request as draft December 10, 2024 14:42
Copy link

codecov bot commented Dec 10, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 77.53%. Comparing base (234704d) to head (6b6357c).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4980   +/-   ##
=======================================
  Coverage   77.53%   77.53%           
=======================================
  Files         103      103           
  Lines        2110     2110           
  Branches      190      190           
=======================================
  Hits         1636     1636           
  Misses        453      453           
  Partials       21       21           
Components Coverage Δ
core 87.80% <ø> (ø)
hooks 79.39% <ø> (ø)
isms 83.68% <ø> (ø)
token 91.27% <ø> (ø)
middlewares 79.80% <ø> (ø)

@xeno097 xeno097 marked this pull request as ready for review December 10, 2024 19:14
Copy link
Member

@yorhodes yorhodes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just reviewed the SDK changes so far. I have come around to eliminating the transformer so lets do it wholesale rather than piecemeal.

Comment on lines +248 to +251
.then((address) => [
multiProvider.getChainName(domainId),
{ interchainAccountRouter: bytes32ToAddress(address) },
]),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: avoid callback syntax and use async/await

Comment on lines +48 to +72
.discriminatedUnion('type', [
z.object({
type: z.literal(TxSubmitterType.JSON_RPC),
}),
z
.object({
type: z.literal(TxSubmitterType.GNOSIS_TX_BUILDER),
})
.merge(EV5GnosisSafeTxBuilderPropsSchema.omit({ chain: true })),
z
.object({
type: z.literal(TxSubmitterType.GNOSIS_SAFE),
})
.merge(EV5GnosisSafeTxSubmitterPropsSchema.omit({ chain: true })),
z
.object({
type: z.literal(TxSubmitterType.IMPERSONATED_ACCOUNT),
})
.merge(
EV5ImpersonatedAccountTxSubmitterPropsSchema.omit({ chain: true }),
),
])
.default({
type: TxSubmitterType.JSON_RPC,
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of duplicating the union here, can we just make this a "recursive" definition and have internalSubmitter be the top level submitter schema?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

otherwise this will be come stale when new submitters are added

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oky, should we then add a limit on the nesting it can be done when creating the strategy config? I created the subtype to make it more difficult to create an invalid/overly complex config

Comment on lines +25 to +48
const EvmIcaTxSubmitterConfigSchema = EvmIcaTxSubmitterPropsSchema.required({
originInterchainAccountRouter: true,
});

/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
const EvmIcaTxSubmitterConstructorConfigSchema =
EvmIcaTxSubmitterConfigSchema.omit({ internalSubmitter: true }).required({
owner: true,
});

type EvmIcaTxSubmitterConfig = z.infer<typeof EvmIcaTxSubmitterConfigSchema>;
type EvmIcaTxSubmitterConstructorConfig = z.infer<
typeof EvmIcaTxSubmitterConstructorConfigSchema
>;

type SubmitterFactoryMapping<
E extends TxSubmitterType,
TConfig extends { type: E },
TResult,
> = {
[K in E]: (
config: Extract<TConfig, { type: K }>,
) => Promise<TResult> | TResult;
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

im a bit confused by the need for all of these

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect to see a similar negative diff for removing the ICA transformer?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldnt this transformer directory be removed entirely?

Comment on lines +19 to +22
import { EV5GnosisSafeTxBuilder } from './ethersV5/EV5GnosisSafeTxBuilder.js';
import { EV5GnosisSafeTxSubmitter } from './ethersV5/EV5GnosisSafeTxSubmitter.js';
import { EV5ImpersonatedAccountTxSubmitter } from './ethersV5/EV5ImpersonatedAccountTxSubmitter.js';
import { EV5JsonRpcTxSubmitter } from './ethersV5/EV5JsonRpcTxSubmitter.js';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really think the ICA submitter should not need to know about these other submitters

Comment on lines +50 to +95
async function getInternalSubmitter(
chain: ChainName,
multiProvider: MultiProvider,
config: EvmIcaTxSubmitterConfig['internalSubmitter'],
): Promise<TxSubmitterInterface<ProtocolType.Ethereum>> {
const internalSubmitterMap: SubmitterFactoryMapping<
EvmIcaTxSubmitterConfig['internalSubmitter']['type'],
EvmIcaTxSubmitterConfig['internalSubmitter'],
TxSubmitterInterface<ProtocolType.Ethereum>
> = {
[TxSubmitterType.GNOSIS_SAFE]: (config) => {
return EV5GnosisSafeTxSubmitter.create(multiProvider, {
chain,
...config,
});
},
[TxSubmitterType.GNOSIS_TX_BUILDER]: (config) => {
return EV5GnosisSafeTxBuilder.create(multiProvider, {
chain,
...config,
});
},
[TxSubmitterType.IMPERSONATED_ACCOUNT]: (config) => {
return new EV5ImpersonatedAccountTxSubmitter(multiProvider, {
chain,
...config,
});
},
[TxSubmitterType.JSON_RPC]: (config) => {
return new EV5JsonRpcTxSubmitter(multiProvider, {
chain,
...config,
});
},
};

const internalSubmitterFactory = internalSubmitterMap[config.type];
// Sanity check
if (!internalSubmitterFactory) {
throw new Error(
`Internal submitter factory not found for type: ${config.type}`,
);
}

return internalSubmitterFactory(config as any);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto here
this doesnt seem like it should be necessary for the ICA submitter to implement

readonly txSubmitterType: TxSubmitterType =
TxSubmitterType.INTERCHAIN_ACCOUNT;

private constructor(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why make this private?

Comment on lines +120 to +121
const owner =
config.owner ?? (await multiProvider.getSignerAddress(config.chain));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems a little dangerous
I would be in favor of making the origin chain and owner address required fields to avoid potential mixups like the one we had

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oky I'll make it required. I agree that it makes it less error-prone and clearer at the same time.

export const EvmIcaTxSubmitterPropsSchema = z.object({
chain: ZChainName,
owner: ZHash.optional(),
destinationChain: ZChainName,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am actually a bit confused by the relationship between the chains/owner and internal submitter
if the internal submitter is a safe submitter then the owner address would have to match? should we remove the chain and owner from this schema entirely?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The chain field specifies which chain the ICA transactions will be sent from, while the owner address is the owner of the ICA so yes in case the internal submitter is a safe, the addresses should match. I think I can enforce this requirement in the zod validator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In Review
Development

Successfully merging this pull request may close these issues.

2 participants